home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 October: Mac OS SDK / Dev.CD Oct 96 SDK / Dev.CD Oct 96 SDK2.toast / Development Kits (Disc 2) / OpenDoc / OpenDoc Development / Debugging Support / OpenDoc Source Code / UI / Undo.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-22  |  57.3 KB  |  2,053 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        Undo.cpp
  3.  
  4.     Contains:    Implementation for Undo class
  5.  
  6.     Owned by:    Nick Pilch
  7.  
  8.     Copyright:    © 1994 - 1996 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.          <3>    .04.1996    NP        1316777: Partiall fix race condition with
  13.                                     the disposal notification process.
  14.         <24>     10/8/95    TJ        Fixes Recomended by Refball
  15.         <23>     9/11/95    NP        1272294: Messaging code cleanup.
  16.         <22>     8/26/95    TÇ        1274606 FB2: Patching Remarks
  17.         <21>     8/23/95    NP        1275237, 1267015: Support for aborting
  18.                                     transactions.
  19.         <20>     8/22/95    eeh        1276821:
  20.                                     kOpenDocShellSignature->kODShellSignature
  21.         <19>     8/16/95    NP        1275241: IDL Review. Remove unnecessary
  22.                                     overrides.
  23.         <18>     8/12/95    TÇ        1276806 Optimization: use kODFalse instead
  24.                                     of kODTrue in comparisons
  25.         <17>      8/7/95    NP        1269965: should be able to nest
  26.                                     transactions, 1269789: Transaction redo
  27.                                     incorrectly implemented.
  28.         <16>      8/3/95    RR        #1257260: Collapse B classes. Remove
  29.                                     somInit methods. Don't call IsInitialized
  30.                                     or SubclassResponsibility
  31.         <15>     7/26/95    DM        #1270320: Memory leak fixes: dispose descs
  32.                                     in NotifyUndoOrRedoOrDispose
  33.         <14>     6/16/95    TJ        Uncommented the pragma export_lib on.
  34.         <13>     6/15/95    NP        1237542: Fix CORBA memory stuff, 1249152:
  35.                                     Undo not respecting marks
  36.         <12>     5/26/95    RR        #1251403: Multithreading naming support
  37.         <11>     5/21/95    NP        1249290: Fix crash if libraries are
  38.                                     preloaded.
  39.         <10>      5/3/95    NP        1211084: Remove 5$
  40.          <9>     4/28/95    NP        1223103: Logic error in Undo. 1243568,
  41.                                     1209554: use of ODGetSystemHeap.
  42.          <8>     4/26/95    NP        1243568: Don't use ODSystemHeap.
  43.          <7>     4/14/95    NP        1238258: Don't use OrderedCollection, use a
  44.                                     collection class that has no virtual
  45.                                     methods and that uses no classes with
  46.                                     virtual methods.
  47.          <6>     4/14/95    NP        1217965: Destroy all system objects when
  48.                                     last doc is closed.
  49.          <5>     1/26/95    eeh        1213354: ODActionData now an ODByteArray.
  50.          <4>     1/25/95    jpa        New ODIText format [1212619]
  51.          <3>    12/25/94    TÇ        1191189 Eliminate duplicate Def.h, Def.xh
  52.                                     files
  53.          <2>     9/29/94    RA        1189812: Mods for 68K build.
  54.          <1>     7/27/94    NP        first checked in
  55.  
  56.     To Do:
  57.         Remove destructors where not needed.
  58.         
  59. */
  60.  
  61.  
  62. #ifndef _PART_
  63. #include "Part.xh"
  64. #endif
  65.  
  66. //#ifndef _ORDCOLL_
  67. //#include "OrdColl.h"
  68. //#endif
  69.  
  70. #ifndef SOM_Module_OpenDoc_StdDefs_defined
  71. #include "StdDefs.xh"
  72. #endif
  73.  
  74. #ifndef _SEUTILS_
  75. #include "SEUtils.h"
  76. #endif
  77.  
  78. #ifndef _ODUTILS_
  79. #include "ODUtils.h"
  80. #endif
  81.  
  82. #ifndef _ITEXT_
  83. #include "IText.h"
  84. #endif
  85.  
  86. #define ODUndo_Class_Source
  87. #define VARIABLE_MACROS
  88. #include <Undo.xih>
  89.  
  90. #ifndef _EXCEPT_
  91. #include <Except.h>
  92. #endif
  93.  
  94. #ifndef _BARRAY_
  95. #include <BArray.h>
  96. #endif
  97.  
  98. //#ifndef _ODNEW_
  99. //#include <ODNew.h>
  100. //#endif
  101.  
  102. #ifndef _ODDEBUG_
  103. #include "ODDebug.h"
  104. #endif
  105.  
  106. //#ifndef _ODTYPES_
  107. //#include "ODTypes.h"
  108. //#endif
  109.  
  110. //#ifndef _PLFMDEF_
  111. //#include "PlfmDef.h"
  112. //#endif
  113.  
  114. //#ifndef _LIST_
  115. //#include "List.h"
  116. //#endif
  117.  
  118. #ifndef _ODMEMORY_
  119. #include "ODMemory.h"
  120. #endif
  121.  
  122. #ifndef __ERRORS__
  123. #include <Errors.h>
  124. #endif
  125.  
  126. #ifndef _ODDEBUG_
  127. #include "ODDebug.h"
  128. #endif
  129.  
  130. #ifndef _TEMPOBJ_
  131. #include <TempObj.h>
  132. #endif
  133.  
  134. #pragma segment ODUndo
  135.  
  136. /*
  137. IMPLEMENTATION NOTES
  138.  
  139. System Heap allocations
  140.  
  141. Almost all memory allocations occur in the system heap.
  142.  
  143. I'm trying to use as little system heap memory as possible because putting
  144. pointers into the system heap could be a bad idea (mem fragmentation).
  145.  
  146. UNDO AND REDO STACKS
  147.  
  148. The stacks are implemented with the UndoOrderedCollection class. The first item
  149. in the collection represents the top of the stack.
  150.  
  151. MARKING
  152.  
  153. When asked to mark a stack that is empty, nothing is done. The code that removes
  154. actions from a stack up to the last mark simply stops when it comes to the end
  155. of a stack.
  156.  
  157. ADDCLIENT, ETC.
  158.  
  159. We need to use these functions to ensure the SystemUndo is freed when
  160. the last OD document is closed. The memory associated with it will have gone
  161. away.
  162. */
  163.  
  164. //==============================================================================
  165. // Special new operator for the system heap that use NewPtrSys and
  166. //    DisposePtr.
  167. //==============================================================================
  168.  
  169. enum ODUndoMemoryAllocation
  170. {
  171.     kODSystemHeap
  172. };
  173.  
  174. void* operator new(size_t size, ODUndoMemoryAllocation allocation);
  175.  
  176. void* operator new(size_t size, ODUndoMemoryAllocation allocation)
  177. {
  178.     void*    retVal;
  179.  
  180.     if (allocation == kODSystemHeap)
  181.         retVal = NewPtrSys(size);
  182.     else
  183.         THROW(kODErrNotImplemented);
  184.     
  185.     return retVal;
  186. }
  187.  
  188. //==============================================================================
  189. // Temporarily include new UndoOrderedCollection class that I can allocate in the
  190. //    system heap. (May be longer than temporary.)
  191. //==============================================================================
  192.  
  193.  
  194.  
  195. /////////////// BEGIN TEMP HACK
  196.  
  197.  
  198.  
  199. //==============================================================================
  200. // UndoLink
  201. //==============================================================================
  202.  
  203. class  UndoLink {
  204.     public:
  205. //        void* operator new(size_t size) {return NewPtrSys(size);}
  206.         void operator delete(void* ptr) {DisposePtr((Ptr)ptr);}
  207.         UndoLink();
  208.         
  209.         UndoLink(UndoLink* next, UndoLink* previous);
  210.         
  211.         UndoLink( const UndoLink& );
  212.         
  213.         ~UndoLink();
  214.         
  215.         UndoLink* GetNext() const                    {return fNext;}
  216.         
  217.         UndoLink* GetPrevious() const                {return fPrevious;}
  218.     
  219.     // The following operations are provided for efficiency, but DO NOT USE THEM
  220.     // if there are any iterators active on a list. These operations don't bump
  221.     // the list's fSeed and the iterators will not be able to detect that they
  222.     // are out of sync!
  223.         
  224.         void  Remove( );
  225.         
  226.         void  AddBefore( UndoLink *aLink );
  227.         
  228.         void  AddAfter( UndoLink *aLink );
  229.     
  230.   //private-by-convention:
  231.           
  232.         void  SetNext(UndoLink* aLink)                {fNext = aLink;}
  233.         
  234.         void  SetPrevious(UndoLink* aLink)            {fPrevious = aLink;}
  235.  
  236.     private:
  237.     
  238.         UndoLink*        fNext;
  239.         UndoLink*        fPrevious;
  240. };
  241.  
  242.  
  243. //==============================================================================
  244. // UndoLinkedList
  245. //==============================================================================
  246.  
  247.  
  248. class UndoLinkedList {
  249.  
  250.     public:
  251.         void operator delete(void* ptr) {DisposePtr((Ptr)ptr);}
  252.           UndoLinkedList();
  253.           
  254.           ~UndoLinkedList();
  255.           
  256.           void            Remove(UndoLink&);
  257.           
  258.           void            AddFirst(UndoLink* link);
  259.           
  260.           UndoLink*            RemoveFirst();
  261.           
  262.           UndoLink*            First()                                            const;
  263.           
  264. protected:
  265.  
  266.         UndoLink            fSentinel;    // Marks the head & tail
  267.         ODULong            fSeed;        // Used to detect out-of-sync iterators
  268.         
  269.         UndoLink*            GetSentinel( )
  270.                                                 {return &fSentinel;}
  271.         const UndoLink*        GetSentinel( )                                    const
  272.                                                 {return &fSentinel;}
  273.         ODBoolean        IsSentinel( const UndoLink* link )                    const
  274.                                                 {return link==this->GetSentinel();}
  275.         ODBoolean        NotSentinel( const UndoLink* link )                    const
  276.                                                 {return link!=this->GetSentinel();}
  277.  
  278. private:                  
  279.         friend class UndoLinkedListIterator;
  280. };
  281.  
  282.  
  283. //=====================================================================================
  284. // UndoLinkedListIterator
  285. //=====================================================================================
  286.  
  287. class UndoLinkedListIterator {
  288.  
  289.     public:
  290.     
  291.         UndoLinkedListIterator(UndoLinkedList*    list);
  292.         
  293.         ~UndoLinkedListIterator();
  294.         
  295.         UndoLink*            First();
  296.         
  297.         UndoLink*            Next();
  298.  
  299.         ODBoolean         IsNotComplete();
  300.         
  301.     private:
  302.     
  303.         UndoLinkedList*        fList;
  304.         UndoLink*            fCurrent;
  305.         UndoLink*            fNext;        // Used only when deleting while iterating
  306.         UndoLink*             fPrevious;    // Used only when deleting while iterating
  307.         UndoLink*            fSentinel;
  308.         ODULong            fSeed;        // Used to detect out-of-sync iterators
  309.         
  310. };
  311.  
  312. //==============================================================================
  313. // Scalar Types
  314. //==============================================================================
  315.  
  316. typedef void* ElementType;
  317.  
  318. //=====================================================================================
  319. // Class UndoValueLink - Definition
  320. //=====================================================================================
  321.  
  322. class UndoValueLink : public UndoLink {
  323.     
  324. public:
  325.                             UndoValueLink(ElementType value);        
  326.                     ~UndoValueLink();
  327.         ElementType    GetValue()                        { return fValue;}
  328.      void        SetValue(ElementType v)            { fValue = v;}
  329.  
  330. private:
  331.     ElementType         fValue;
  332. };
  333.  
  334. //=====================================================================================
  335. // Class UndoOrderedCollection
  336. //=====================================================================================
  337.  
  338. class UndoOrderedCollection
  339. {
  340.     
  341. public:
  342.     void operator delete(void* ptr) {DisposePtr((Ptr)ptr);}
  343.     UndoOrderedCollection();
  344.     UndoOrderedCollection(ODUndoMemoryAllocation where);
  345.     ~UndoOrderedCollection();
  346.  
  347.      void    AddFirst(ElementType element);
  348.      ElementType    First();
  349.         // Returns kODNULL if there is no first element.
  350.      ElementType    RemoveFirst();
  351.         // Don't call if there are no elements. Crash will result.
  352.      void    Remove(ElementType existing);
  353.      void    RemoveAll();
  354.     
  355.         // Called from the destructor. Removes all elements, deleting the links
  356.         // Does not delete the elements themselves
  357.  
  358. protected:
  359.       UndoValueLink*     CreateNewLink(ElementType value) const;
  360.       ODBoolean    ElementsMatch(ElementType v1,ElementType v2) const;
  361.          // Does a pointer comparison by default 
  362.  
  363. private:
  364.     UndoLinkedList        fImplementation;
  365.     ODUndoMemoryAllocation    fHeap; // if kODNULL, use default heap.
  366.  
  367.     friend class UndoOrderedCollectionIterator;
  368.     friend class ListIterator;
  369. };
  370.  
  371. //=====================================================================================
  372. // Class UndoOrderedCollectionIterator
  373. //=====================================================================================
  374.  
  375. class UndoOrderedCollectionIterator {
  376. public:
  377.     UndoOrderedCollectionIterator(UndoOrderedCollection* collection);
  378.     ~UndoOrderedCollectionIterator();
  379.     ElementType    First();
  380.     ElementType    Next();
  381.     ODBoolean    IsNotComplete();
  382.     
  383. private:
  384.       UndoOrderedCollection*    fCollection;
  385.     UndoLinkedListIterator    fImplementation;
  386. };
  387.  
  388. //==============================================================================
  389. // UndoLink
  390. //==============================================================================
  391.  
  392.  
  393.  
  394. // Many of the simple link methods are inlines; see List.h for implementations.
  395.  
  396.  
  397. //------------------------------------------------------------------------------
  398. // UndoLink::UndoLink
  399. //
  400. // Constructor for UndoLink
  401. //------------------------------------------------------------------------------
  402.  
  403. UndoLink::UndoLink()                            
  404.     fNext = kODNULL; 
  405.     fPrevious = kODNULL;
  406. }
  407.  
  408. //------------------------------------------------------------------------------
  409. // UndoLink::UndoLink
  410. //
  411. // Constructor for UndoLink
  412. //------------------------------------------------------------------------------
  413.  
  414. UndoLink::UndoLink(UndoLink* next, UndoLink* previous)                            
  415.     fNext = next; 
  416.     fPrevious = previous;
  417. }
  418.  
  419. //------------------------------------------------------------------------------
  420. // UndoLink::UndoLink
  421. //
  422. // Copy constructor for UndoLink
  423. //------------------------------------------------------------------------------
  424.  
  425. UndoLink::UndoLink( const UndoLink &link )                            
  426.     fNext = link.fNext; 
  427.     fPrevious = link.fPrevious;
  428. }
  429.  
  430. //------------------------------------------------------------------------------
  431. // UndoLink::UndoLink
  432. //
  433. // Destructor for UndoLink
  434. //------------------------------------------------------------------------------
  435.  
  436. UndoLink::~UndoLink()                                            
  437. {
  438. }
  439.  
  440. //------------------------------------------------------------------------------
  441. // UndoLink::Remove
  442. //
  443. // Remove a link from its list (if any). DO NOT call this directly if there are
  444. // any iterators active on the list; use UndoLinkedList::Remove instead.
  445. //------------------------------------------------------------------------------
  446.  
  447. void    UndoLink::Remove( )
  448. {
  449.     if( fPrevious )
  450.         fPrevious->SetNext(fNext);
  451.     if( fNext )
  452.         fNext->SetPrevious(fPrevious);
  453.     fNext = kODNULL;
  454.     fPrevious = kODNULL;
  455. }
  456.  
  457. //------------------------------------------------------------------------------
  458. // UndoLink::AddBefore
  459. //
  460. // Add a link to a list before another link. It must not already be on any list.
  461. // DO NOT call this directly if there are any iterators active on the list;
  462. // use UndoLinkedList::Remove instead.
  463. //------------------------------------------------------------------------------
  464.  
  465. void    UndoLink::AddBefore( UndoLink *link )
  466. {
  467.     ASSERT(link!=kODNULL,paramErr);
  468.     WASSERT(fNext==kODNULL);
  469.     WASSERT(fPrevious==kODNULL);
  470.     fNext = link;
  471.     fPrevious = link->GetPrevious();
  472.     fPrevious->SetNext(this);
  473.     fNext->SetPrevious(this);
  474. }
  475.  
  476. //------------------------------------------------------------------------------
  477. // UndoLink::AddAfter
  478. //
  479. // Add a link to a list after another link. It must not already be on any list.
  480. // DO NOT call this directly if there are any iterators active on the list;
  481. // use UndoLinkedList::Remove instead.
  482. //------------------------------------------------------------------------------
  483.  
  484. void    UndoLink::AddAfter( UndoLink *link )
  485. {
  486.     ASSERT(link!=kODNULL,paramErr);
  487.     WASSERT(fNext==kODNULL);
  488.     WASSERT(fPrevious==kODNULL);
  489.     fPrevious = link;
  490.     fNext = link->GetNext();
  491.     fPrevious->SetNext(this);
  492.     fNext->SetPrevious(this);
  493. }
  494.  
  495. //======================================================================================
  496. // Class UndoLinkedList
  497. //======================================================================================
  498.  
  499. //------------------------------------------------------------------------------
  500. // UndoLinkedList::UndoLinkedList
  501. //
  502. // Constructor for UndoLinkedList
  503. //------------------------------------------------------------------------------
  504.  
  505. UndoLinkedList::UndoLinkedList()
  506.     :fSentinel(&fSentinel,&fSentinel),
  507.      fSeed(0)
  508. {
  509. }
  510.  
  511. //------------------------------------------------------------------------------
  512. // UndoLinkedList::~UndoLinkedList
  513. //
  514. // Destructor for UndoLinkedList
  515. //------------------------------------------------------------------------------
  516.  
  517. UndoLinkedList::~UndoLinkedList()
  518. {
  519.     // The list does NOT delete all its links!
  520. }
  521.  
  522. //------------------------------------------------------------------------------
  523. // UndoLinkedList::Remove
  524. //
  525. // Description
  526. //------------------------------------------------------------------------------
  527.  
  528. void    UndoLinkedList::Remove(UndoLink& aLink)
  529. {
  530.     fSeed++;
  531.     aLink.Remove();
  532. }
  533.  
  534. //------------------------------------------------------------------------------
  535. // UndoLinkedList::RemoveFirst
  536. //
  537. // Description
  538. //------------------------------------------------------------------------------
  539.  
  540. UndoLink* UndoLinkedList::RemoveFirst()
  541. {
  542.     UndoLink* old = fSentinel.GetNext();
  543.     if (this->NotSentinel(old))
  544.     {
  545.         fSeed++;
  546.         old->Remove();
  547.         return old;
  548.     }
  549.     else
  550.     {
  551.         return kODNULL;
  552.     }
  553. }
  554.  
  555. //------------------------------------------------------------------------------
  556. // UndoLinkedList::AddFirst
  557. //
  558. // Description
  559. //------------------------------------------------------------------------------
  560.  
  561. void    UndoLinkedList::AddFirst(UndoLink* link)
  562. {
  563.     link->AddAfter(this->GetSentinel());
  564.     fSeed++;
  565. }
  566.  
  567. //------------------------------------------------------------------------------
  568. // UndoLinkedList::First
  569. //
  570. // Description
  571. //------------------------------------------------------------------------------
  572.  
  573. UndoLink*    UndoLinkedList::First()  const
  574. {
  575.     return this->NotSentinel(fSentinel.GetNext()) ? fSentinel.GetNext() : (UndoLink*) kODNULL;
  576. }
  577.  
  578. //======================================================================================
  579. // Class UndoLinkedListIterator
  580. //======================================================================================
  581.  
  582. //------------------------------------------------------------------------------
  583. // UndoLinkedListIterator::UndoLinkedListIterator
  584. //
  585. // Constructor for UndoLinkedListIterator
  586. //------------------------------------------------------------------------------
  587.  
  588. UndoLinkedListIterator::UndoLinkedListIterator(UndoLinkedList* list)
  589. {
  590.     fList = list;
  591.     fCurrent = kODNULL;
  592.     fNext = kODNULL;
  593.     fPrevious = kODNULL;
  594.     fSentinel = &list->fSentinel;
  595.     fSeed = fList->fSeed;    
  596. }
  597.  
  598. //------------------------------------------------------------------------------
  599. // UndoLinkedListIterator::~UndoLinkedListIterator
  600. //
  601. // Destructor for UndoLinkedListIterator
  602. //------------------------------------------------------------------------------
  603.  
  604. UndoLinkedListIterator::~UndoLinkedListIterator()
  605. {
  606. }
  607.  
  608. //------------------------------------------------------------------------------
  609. // UndoLinkedListIterator::First
  610. //
  611. // Description
  612. //------------------------------------------------------------------------------
  613.  
  614. UndoLink* UndoLinkedListIterator::First()
  615. {
  616.     if (fList == kODNULL)
  617.         return kODNULL;
  618.         
  619.     if (fSeed != fList->fSeed)
  620.         THROW(kODErrIteratorOutOfSync);
  621.         
  622.     fCurrent = fList->First();
  623.     if (fCurrent == fSentinel)
  624.         fCurrent = kODNULL;
  625.     return fCurrent;
  626. }
  627.  
  628. //------------------------------------------------------------------------------
  629. // UndoLinkedListIterator::Next
  630. //
  631. // Description
  632. //------------------------------------------------------------------------------
  633.  
  634. UndoLink* UndoLinkedListIterator::Next()
  635. {
  636.     if (fList == kODNULL)
  637.         return kODNULL;
  638.  
  639.     if (fSeed != fList->fSeed)
  640.         THROW(kODErrIteratorOutOfSync);
  641.  
  642.     if (fCurrent == kODNULL)
  643.     {
  644.         if ((fNext == kODNULL) && (fPrevious == kODNULL))    // Just starting out
  645.         {
  646.             return this->First();
  647.         }
  648.         else    // Just deleted
  649.         {
  650.             fCurrent = fNext;
  651.             fPrevious = kODNULL;
  652.             fNext = kODNULL;
  653.         }
  654.     }
  655.     else
  656.         fCurrent = fCurrent->GetNext();
  657.     
  658.     if (fCurrent == fSentinel)
  659.         fCurrent = kODNULL;
  660.     return fCurrent;
  661. }
  662.  
  663. //------------------------------------------------------------------------------
  664. // UndoLinkedListIterator::IsNotComplete
  665. //
  666. // Description
  667. //------------------------------------------------------------------------------
  668.  
  669. ODBoolean UndoLinkedListIterator::IsNotComplete()
  670. {
  671.     return (fCurrent != kODNULL);
  672. }
  673.  
  674. //======================================================================================
  675. // Class UndoValueLink - Implementation
  676. //======================================================================================
  677.  
  678. UndoValueLink::UndoValueLink(ElementType value)
  679. {
  680.     fValue = value;
  681. }
  682.  
  683. UndoValueLink::~UndoValueLink()
  684. {
  685. }
  686.  
  687. //======================================================================================
  688. // Class UndoOrderedCollection
  689. //======================================================================================
  690.  
  691. //------------------------------------------------------------------------------
  692. // UndoOrderedCollection::UndoOrderedCollection
  693. //------------------------------------------------------------------------------
  694.  
  695. UndoOrderedCollection::UndoOrderedCollection()
  696. {
  697.     fHeap = kODSystemHeap;
  698. }
  699.  
  700. //------------------------------------------------------------------------------
  701. // UndoOrderedCollection::UndoOrderedCollection
  702. //------------------------------------------------------------------------------
  703.  
  704. UndoOrderedCollection::UndoOrderedCollection(ODUndoMemoryAllocation where)
  705. {
  706.     fHeap = where;
  707. }
  708.  
  709. // UndoOrderedCollection::~UndoOrderedCollection
  710. //------------------------------------------------------------------------------
  711.  
  712. UndoOrderedCollection::~UndoOrderedCollection()
  713. {
  714.     this->RemoveAll();
  715. }
  716.  
  717. //------------------------------------------------------------------------------
  718. // UndoOrderedCollection::AddFirst
  719. //------------------------------------------------------------------------------
  720.  
  721. void UndoOrderedCollection::AddFirst(ElementType element)
  722. {
  723.     UndoValueLink* newLink = this->CreateNewLink(element);
  724.     fImplementation.AddFirst(newLink);
  725. }
  726.  
  727. //------------------------------------------------------------------------------
  728. // UndoOrderedCollection::First
  729. //------------------------------------------------------------------------------
  730.  
  731. ElementType UndoOrderedCollection::First()
  732. {
  733.     UndoValueLink* firstLink = (UndoValueLink*) fImplementation.First();
  734.     return firstLink ? firstLink->GetValue() : (ElementType)kODNULL;
  735. }
  736.  
  737. //------------------------------------------------------------------------------
  738. // UndoOrderedCollection::RemoveFirst
  739. //------------------------------------------------------------------------------
  740.  
  741. ElementType    UndoOrderedCollection::RemoveFirst()
  742. {
  743.     UndoValueLink* aLink = (UndoValueLink*) fImplementation.RemoveFirst();
  744.     ElementType value = aLink ? aLink->GetValue() : kODNULL;
  745.     delete aLink;
  746.     return value;
  747. }
  748.  
  749. //------------------------------------------------------------------------------
  750. // UndoOrderedCollection::Remove
  751. //------------------------------------------------------------------------------
  752.  
  753. void UndoOrderedCollection::Remove(ElementType existing)
  754. {
  755.     UndoLinkedListIterator iter(&fImplementation);
  756.     UndoValueLink* aLink = (UndoValueLink*) iter.First();
  757.     while (aLink != kODNULL)
  758.     {
  759.         ElementType v = ((UndoValueLink*) aLink)->GetValue();
  760.  
  761.         if (this->ElementsMatch(v,existing))
  762.         {
  763.             fImplementation.Remove(*aLink);
  764.             delete aLink;
  765.             aLink = kODNULL;    
  766.         }
  767.         else
  768.             aLink = (UndoValueLink*) iter.Next();
  769.     }    
  770. }
  771.  
  772. //------------------------------------------------------------------------------
  773. // UndoOrderedCollection::RemoveAll
  774. //------------------------------------------------------------------------------
  775.  
  776. void UndoOrderedCollection::RemoveAll()
  777. {
  778.     UndoLink* link = fImplementation.RemoveFirst();
  779.     while (link != kODNULL)
  780.     {
  781.         delete link;
  782.         link = fImplementation.RemoveFirst();
  783.     }
  784. }
  785.  
  786. //------------------------------------------------------------------------------
  787. // UndoOrderedCollection::CreateNewLink
  788. //------------------------------------------------------------------------------
  789.  
  790. UndoValueLink*    UndoOrderedCollection::CreateNewLink(ElementType value) const
  791. {
  792.     return new (fHeap) UndoValueLink(value);
  793. }
  794.  
  795. //------------------------------------------------------------------------------
  796. // UndoOrderedCollection::ElementsMatch
  797. //------------------------------------------------------------------------------
  798.  
  799. ODBoolean    UndoOrderedCollection::ElementsMatch(ElementType v1,ElementType v2) const
  800. {
  801.     return (v1 == v2);
  802. }
  803.  
  804. //======================================================================================
  805. // UndoOrderedCollectionIterator
  806. //======================================================================================
  807.  
  808. //------------------------------------------------------------------------------
  809. // UndoOrderedCollectionIterator::UndoOrderedCollectionIterator
  810. //------------------------------------------------------------------------------
  811.  
  812. UndoOrderedCollectionIterator::UndoOrderedCollectionIterator(UndoOrderedCollection* collection)    
  813.     : fImplementation(collection ? &(collection->fImplementation) : (UndoLinkedList*)kODNULL)
  814. {
  815.     fCollection =  collection;
  816. }
  817.  
  818. //------------------------------------------------------------------------------
  819. // UndoOrderedCollectionIterator::~UndoOrderedCollectionIterator
  820. //------------------------------------------------------------------------------
  821.  
  822. UndoOrderedCollectionIterator::~UndoOrderedCollectionIterator()                        
  823. {
  824. }
  825.  
  826. //------------------------------------------------------------------------------
  827. // UndoOrderedCollectionIterator::First
  828. //------------------------------------------------------------------------------
  829.  
  830. ElementType    UndoOrderedCollectionIterator::First()
  831. {
  832.     UndoValueLink* link = (UndoValueLink*) fImplementation.First();
  833.     
  834.     return link ? link->GetValue() : (ElementType)kODNULL;
  835. }
  836.  
  837. //------------------------------------------------------------------------------
  838. // UndoOrderedCollectionIterator::Next
  839. //------------------------------------------------------------------------------
  840.  
  841. ElementType    UndoOrderedCollectionIterator::Next()
  842. {        
  843.     UndoValueLink* link = (UndoValueLink*) fImplementation.Next();
  844.     
  845.     return link ? link->GetValue() : (ElementType)kODNULL;
  846. }
  847.  
  848. //------------------------------------------------------------------------------
  849. // UndoOrderedCollectionIterator::IsNotComplete
  850. //------------------------------------------------------------------------------
  851.  
  852. ODBoolean    UndoOrderedCollectionIterator::IsNotComplete()
  853. {
  854.     return fImplementation.IsNotComplete();
  855. }
  856.  
  857.  
  858.  
  859. /////////////// END TEMP HACK
  860.  
  861.  
  862.  
  863. //==============================================================================
  864. // Constants
  865. //==============================================================================
  866.  
  867. const OSType kUndoNotifyID = 'undo';
  868. const OSType kRedoNotifyID = 'redo';
  869. const OSType kDisposeActionNotifyID = 'del ';
  870.  
  871. const AEKeyword kDataPtrKeyword = 'data';
  872. const AEKeyword kPartPtrKeyword = 'part';
  873. const AEKeyword kDoneStateKeyword = 'done';
  874.  
  875. // A number of functions can share code. They pass along this enum to know
  876. //    which course of action to take.
  877. enum ODUndoRedoType
  878. {
  879.     kUndo,
  880.     kRedo,
  881.     kDispose
  882. };
  883.  
  884. //==============================================================================
  885. // Classes used in this file
  886. //==============================================================================
  887.  
  888. class UndoAction;
  889. class SystemUndo;
  890.  
  891. //==============================================================================
  892. // Function Prototypes
  893. //==============================================================================
  894.  
  895. static OSErr NotifyUndoOrRedoOrDispose(UndoAction* action,
  896.                                                 ODUndoRedoType which);
  897. static OSErr NotifyUndo(UndoAction* action);
  898. static OSErr NotifyRedo(UndoAction* action);
  899. static OSErr NotifyDispose(UndoAction* action);
  900. static SystemUndo *GetSystemUndo();
  901. static ODBoolean SetSystemUndo(SystemUndo *systemUndo);
  902.  
  903. //==============================================================================
  904. // Functions
  905. //==============================================================================
  906.  
  907. // • Using ASLM we registered the system undo object with ASLM using the
  908. // arbitration mechanism provided by ASLM. To eliminate our dependency on ASLM
  909. // we are storing the system undo object in a global which is accessed by the
  910. // following two functions. This is NOT a thread safe method for accessing the
  911. // system undo!
  912.  
  913. //------------------------------------------------------------------------------
  914. // GetSystemUndo
  915. //------------------------------------------------------------------------------
  916.  
  917. #pragma lib_export on
  918. extern SystemUndo* gSystemUndo;        
  919. #pragma lib_export off
  920.  
  921. static SystemUndo *GetSystemUndo()
  922. {
  923.     return gSystemUndo;
  924. }
  925.  
  926. //------------------------------------------------------------------------------
  927. // SetSystemUndo
  928. //------------------------------------------------------------------------------
  929.  
  930. static ODBoolean SetSystemUndo(SystemUndo *systemUndo)
  931. {
  932.     gSystemUndo = systemUndo;
  933.     return kODTrue;
  934. }
  935.  
  936. //#pragma lib_export off
  937.  
  938. //==============================================================================
  939. // Local Classes
  940. //==============================================================================
  941.  
  942. //------------------------------------------------------------------------------
  943.  
  944. class UndoAction
  945. {
  946.   public:
  947.         void operator delete(void* ptr) {DisposePtr((Ptr)ptr);}
  948.     UndoAction(ODPart* whichPart, ODActionData* actionData,
  949.                     ODActionType actionType, ODName* undoActionLabel,
  950.                     ODName* redoActionLabel);
  951.     ~UndoAction();
  952.  
  953.     ODPart*                fPart;
  954.     ProcessSerialNumber    fProcessNum;
  955.     ODActionData*        fActionData;
  956.     ODActionType        fActionType;
  957.     ODName*                fUndoActionLabel;
  958.     ODName*                fRedoActionLabel;
  959.     ODBoolean            fMark;
  960.     ODDoneState            fDoneState;
  961. };
  962.  
  963. //------------------------------------------------------------------------------
  964. // UndoAction::UndoAction
  965. //
  966. //    This constructor may throw an error, but it's OK because there is nothing
  967. //    to deallocate in the destructor.
  968. //------------------------------------------------------------------------------
  969.  
  970. UndoAction::UndoAction(ODPart* whichPart, 
  971.                                     ODActionData* actionData,
  972.                                     ODActionType actionType,
  973.                                     ODName* undoActionLabel,
  974.                                     ODName* redoActionLabel)
  975. {
  976.     fPart = whichPart;
  977.     THROW_IF_ERROR(GetCurrentProcess(&fProcessNum));
  978.     fActionData = actionData;
  979.     fActionType = actionType;
  980.     fUndoActionLabel = undoActionLabel;
  981.     fRedoActionLabel = redoActionLabel;
  982.     fMark = kODFalse;
  983.     fDoneState = kODDone;
  984. }
  985.  
  986. //------------------------------------------------------------------------------
  987. // UndoAction::~UndoAction
  988. //
  989. //    Notify owning part owning fActionData to dipose of any associated memory.
  990. //------------------------------------------------------------------------------
  991.  
  992. UndoAction::~UndoAction()
  993. {
  994.     NotifyDispose(this);
  995.  
  996.     DisposeIText(fUndoActionLabel);
  997.     DisposeIText(fRedoActionLabel);
  998.     DisposeByteArray(fActionData);
  999. }
  1000.  
  1001. //------------------------------------------------------------------------------
  1002.  
  1003. class SystemUndo
  1004. {
  1005.   public:
  1006.         void operator delete(void* ptr) {DisposePtr((Ptr)ptr);}
  1007.     SystemUndo();
  1008.     ~SystemUndo();
  1009.     void    Initialize();
  1010.  
  1011.     ODSize        Purge(ODSize size);
  1012.     ODBoolean    CheckActionOK(UndoAction* action);
  1013.     void        AddActionToHistory(ODPart* whichPart, 
  1014.                                     ODActionData* actionData,
  1015.                                     ODActionType actionType,
  1016.                                     ODName* undoActionLabel,
  1017.                                     ODName* redoActionLabel);
  1018.     void    Undo();
  1019.     void    Redo();
  1020.     void    MarkActionHistory();
  1021.     void    ClearActionHistory(ODRespectMarksChoices respectMarks);
  1022.     void    ClearRedoHistory();
  1023.     ODBoolean    PeekUndoHistory(ODPart** part,
  1024.                                 ODActionData* actionData,
  1025.                                 ODActionType* actionType,
  1026.                                 ODName* actionLabel);
  1027.     ODBoolean    PeekRedoHistory(ODPart** part,
  1028.                                 ODActionData* actionData,
  1029.                                 ODActionType* actionType,
  1030.                                 ODName* actionLabel);
  1031.     void        RemoveEntriesForThisProcess();
  1032.     void        AddClient(ODUndo* docUndoObject);
  1033.     void        RemoveClient(ODUndo* docUndoObject);
  1034.     ODULong        GetNumClients();
  1035.     void        AbortCurrentTransaction();
  1036.   private:
  1037.     void        TransactionUndo(UndoAction* firstAction);
  1038.     void        TransactionRedo(UndoAction* firstAction);
  1039.     void        MarkActionOrSelf(UndoAction* action, ODBoolean* mark);
  1040.     void        ClearActionsToMark(UndoOrderedCollection* stack);
  1041.     void        ClearStack(UndoOrderedCollection* stack);
  1042.     ODBoolean    PeekHistory(ODPart** part,
  1043.                                 ODActionData* actionData,
  1044.                                 ODActionType* actionType,
  1045.                                 ODName* actionLabel,
  1046.                                 ODUndoRedoType which);
  1047.     void        MoveUndoToRedo();
  1048.     void        MoveRedoToUndo();
  1049.  
  1050.     UndoOrderedCollection*        fUndoStack;
  1051.     UndoOrderedCollection*        fRedoStack;
  1052.     ODULong                        fInTransaction;
  1053.     ODBoolean                fCurrentlyUndoingOrRedoing;
  1054.     ODULong                fNumUsers;
  1055. };
  1056.  
  1057. //------------------------------------------------------------------------------
  1058. // SystemUndo::SystemUndo
  1059. //------------------------------------------------------------------------------
  1060.  
  1061. SystemUndo::SystemUndo()
  1062. {
  1063.     fUndoStack = kODNULL;
  1064.     fRedoStack = kODNULL;
  1065.     fInTransaction = 0;
  1066.     fCurrentlyUndoingOrRedoing = kODFalse;
  1067.     fNumUsers = 0;
  1068. }
  1069.  
  1070. //------------------------------------------------------------------------------
  1071. // SystemUndo::Initialize                
  1072. //------------------------------------------------------------------------------
  1073.  
  1074. void SystemUndo::Initialize ()
  1075. {
  1076.     ODUndoMemoryAllocation    heap = kODSystemHeap;
  1077.  
  1078.     fUndoStack = new (heap) UndoOrderedCollection(heap);
  1079.     fRedoStack = new (heap) UndoOrderedCollection(heap);
  1080.  
  1081. }
  1082.  
  1083. //------------------------------------------------------------------------------
  1084. // SystemUndo::~SystemUndo
  1085. //------------------------------------------------------------------------------
  1086.  
  1087. SystemUndo::~SystemUndo()
  1088. {
  1089. //    WASSERTM(0, "System Undo object being destroyed!");
  1090.     delete fUndoStack;
  1091.     delete fRedoStack;
  1092. }
  1093.  
  1094. //------------------------------------------------------------------------------
  1095. // SystemUndo::Purge
  1096. //------------------------------------------------------------------------------
  1097.         
  1098. ODSize    SystemUndo::Purge(ODSize size)
  1099. {
  1100.     ODUnused(size);
  1101.     return 0;
  1102. }
  1103.  
  1104. //------------------------------------------------------------------------------
  1105. // SystemUndo::CheckActionOK
  1106. //------------------------------------------------------------------------------
  1107.         
  1108. ODBoolean SystemUndo::CheckActionOK(UndoAction* action)
  1109. {
  1110.     if (action && !(action->fMark))
  1111.         return kODTrue;
  1112.     return kODFalse;
  1113. }
  1114.  
  1115. //------------------------------------------------------------------------------
  1116. // SystemUndo::AddClient
  1117. //------------------------------------------------------------------------------
  1118.         
  1119. void SystemUndo::AddClient(ODUndo* docUndoObject)
  1120. {
  1121.     ODUnused(docUndoObject);
  1122.     ++fNumUsers;
  1123. }
  1124.  
  1125. //------------------------------------------------------------------------------
  1126. // SystemUndo::RemoveClient
  1127. //------------------------------------------------------------------------------
  1128.         
  1129. void SystemUndo::RemoveClient(ODUndo* docUndoObject)
  1130. {
  1131.     ODUnused(docUndoObject);
  1132.     --fNumUsers;
  1133. }
  1134.  
  1135. //------------------------------------------------------------------------------
  1136. // SystemUndo::GetNumClients
  1137. //------------------------------------------------------------------------------
  1138.         
  1139. ODULong SystemUndo::GetNumClients()
  1140. {
  1141.     return fNumUsers;
  1142. }
  1143.  
  1144. //------------------------------------------------------------------------------
  1145. // SystemUndo::AddActionToHistory
  1146. //------------------------------------------------------------------------------
  1147.  
  1148. void SystemUndo::AddActionToHistory(ODPart* whichPart, 
  1149.                                     ODActionData* actionData,
  1150.                                     ODActionType actionType,
  1151.                                     ODName* undoActionLabel,
  1152.                                     ODName* redoActionLabel)
  1153. {
  1154.     if (fCurrentlyUndoingOrRedoing)
  1155.         THROW(kODErrCannotAddAction);
  1156.  
  1157. //    if (fInTransaction && actionType == kODBeginAction)
  1158. //        THROW(kODErrCannotAddAction);
  1159.  
  1160.     if (actionType == kODBeginAction)
  1161.         ++fInTransaction;
  1162.     if (actionType == kODEndAction)
  1163.         --fInTransaction;
  1164.  
  1165.     // NOT DOING THESE ALLOCATIONS IN THE SYSTEM HEAP!
  1166.     ODIText* undoName = CopyIText(undoActionLabel);
  1167.     ODIText* redoName = CopyIText(redoActionLabel);
  1168.  
  1169.     ODActionData* copiedData = (ODActionData*)ODNewPtr(sizeof(ODActionData));
  1170.     copiedData->_buffer = (octet*)ODNewPtr(actionData->_length);
  1171.     ODBlockMove(actionData->_buffer, copiedData->_buffer, actionData->_length);
  1172.     copiedData->_length = actionData->_length;
  1173.     copiedData->_maximum = actionData->_length;
  1174.  
  1175.     UndoAction* action =
  1176.                     new (kODSystemHeap) UndoAction(whichPart, copiedData,
  1177.                                                     actionType, undoName,
  1178.                                                     redoName);
  1179.     fUndoStack->AddFirst(action);
  1180.     this->ClearStack(fRedoStack);
  1181. }
  1182.  
  1183. //------------------------------------------------------------------------------
  1184. // SystemUndo::MoveUndoToRedo
  1185. //
  1186. //    Utility to move item from top of one stack to the top of another.
  1187. //------------------------------------------------------------------------------
  1188.  
  1189. void SystemUndo::MoveUndoToRedo()
  1190. {
  1191.     ElementType item = fUndoStack->RemoveFirst();
  1192.     ((UndoAction*)item)->fDoneState = kODUndone;
  1193.     fRedoStack->AddFirst(item);
  1194. }
  1195.  
  1196. //------------------------------------------------------------------------------
  1197. // SystemUndo::MoveRedoToUndo
  1198. //
  1199. //    Utility to move item from top of one stack to the top of another.
  1200. //------------------------------------------------------------------------------
  1201.  
  1202. void SystemUndo::MoveRedoToUndo()
  1203. {
  1204.     ElementType item = fRedoStack->RemoveFirst();
  1205.     ((UndoAction*)item)->fDoneState = kODRedone;
  1206.     fUndoStack->AddFirst(item);
  1207. }
  1208.  
  1209. //------------------------------------------------------------------------------
  1210. // SystemUndo::Undo
  1211. //
  1212. //    If there's an error while undoing anything, just clear the stacks and get
  1213. //    out.
  1214. //------------------------------------------------------------------------------
  1215.  
  1216. void SystemUndo::Undo()
  1217. {
  1218.     UndoAction* action = (UndoAction*)fUndoStack->First();
  1219.     if (!this->CheckActionOK(action))
  1220.         THROW(kODErrEmptyStack);
  1221.  
  1222.     fCurrentlyUndoingOrRedoing = kODTrue;
  1223.  
  1224.     TRY
  1225.         if (action->fActionType == kODEndAction) // End is at top for an Undo
  1226.             this->TransactionUndo(action);
  1227.         else
  1228.         {
  1229.             THROW_IF_ERROR(NotifyUndo(action));
  1230.             this->MoveUndoToRedo();
  1231.         }
  1232.     CATCH_ALL
  1233.         this->ClearActionHistory(kODDontRespectMarks);
  1234.         fCurrentlyUndoingOrRedoing = kODFalse;
  1235.         RERAISE;
  1236.     ENDTRY
  1237.     fCurrentlyUndoingOrRedoing = kODFalse;
  1238. }
  1239.  
  1240. //------------------------------------------------------------------------------
  1241. // SystemUndo::TransactionUndo
  1242. //------------------------------------------------------------------------------
  1243.  
  1244. void SystemUndo::TransactionUndo(UndoAction* firstAction)
  1245. {
  1246.     UndoAction*    action;
  1247.     ODULong        nestedTransactionCounter = 1;
  1248.  
  1249.     THROW_IF_ERROR(NotifyUndo(firstAction));
  1250.     this->MoveUndoToRedo();
  1251.  
  1252.     do
  1253.     {
  1254.         action = (UndoAction*)fUndoStack->First();
  1255.         if (action == (UndoAction*)kODNULL)
  1256.             THROW(kODErrNoBeginAction);
  1257.         THROW_IF_ERROR(NotifyUndo(action));
  1258.         this->MoveUndoToRedo();
  1259.         if (action->fActionType == kODBeginAction)
  1260.             --nestedTransactionCounter;
  1261.         else if (action->fActionType == kODEndAction)
  1262.             ++nestedTransactionCounter;
  1263.     }
  1264.     while (nestedTransactionCounter);
  1265. }
  1266.  
  1267. //------------------------------------------------------------------------------
  1268. // SystemUndo::Redo
  1269. //------------------------------------------------------------------------------
  1270.  
  1271. void SystemUndo::Redo()
  1272. {
  1273.     UndoAction* action = (UndoAction*)fRedoStack->First();
  1274.     if (!this->CheckActionOK(action))
  1275.         THROW(kODErrEmptyStack);
  1276.  
  1277.     fCurrentlyUndoingOrRedoing = kODTrue;
  1278.  
  1279.     TRY
  1280.         if (action->fActionType == kODBeginAction)//Start is at top for an Redo
  1281.             this->TransactionRedo(action);
  1282.         else
  1283.         {
  1284.             THROW_IF_ERROR(NotifyRedo(action));
  1285.             this->MoveRedoToUndo();
  1286.         }
  1287.     CATCH_ALL
  1288.         this->ClearActionHistory(kODDontRespectMarks);
  1289.         fCurrentlyUndoingOrRedoing = kODFalse;
  1290.         RERAISE;
  1291.     ENDTRY
  1292.     fCurrentlyUndoingOrRedoing = kODFalse;
  1293. }
  1294.  
  1295. //------------------------------------------------------------------------------
  1296. // SystemUndo::TransactionRedo
  1297. //------------------------------------------------------------------------------
  1298.  
  1299. void SystemUndo::TransactionRedo(UndoAction* firstAction)
  1300. {
  1301.     UndoAction*    action;
  1302.     ODULong        nestedTransactionCounter = 1;
  1303.  
  1304.     THROW_IF_ERROR(NotifyRedo(firstAction));
  1305.     this->MoveRedoToUndo();
  1306.  
  1307.     do
  1308.     {
  1309.         action = (UndoAction*)fRedoStack->First();
  1310. //        if (action == (UndoAction*)kODNULL)
  1311. //            THROW(kODErrNoBeginAction);
  1312.         THROW_IF_ERROR(NotifyRedo(action));
  1313.         this->MoveRedoToUndo();
  1314.         if (action->fActionType == kODBeginAction)
  1315.             ++nestedTransactionCounter;
  1316.         else if (action->fActionType == kODEndAction)
  1317.             --nestedTransactionCounter;
  1318.     }
  1319.     while (nestedTransactionCounter);
  1320. }
  1321.  
  1322. //------------------------------------------------------------------------------
  1323. // SystemUndo::MarkActionHistory
  1324. //------------------------------------------------------------------------------
  1325.  
  1326. void SystemUndo::MarkActionHistory()
  1327. {
  1328.     UndoAction*    action;
  1329.  
  1330.     action = (UndoAction*)fUndoStack->First();
  1331.     if (action)
  1332.         action->fMark = kODTrue;
  1333.     action = (UndoAction*)fRedoStack->First();
  1334.     if (action)
  1335.         action->fMark = kODTrue;
  1336. }
  1337.  
  1338. //------------------------------------------------------------------------------
  1339. // SystemUndo::ClearStack
  1340. //------------------------------------------------------------------------------
  1341.  
  1342. void SystemUndo::ClearStack(UndoOrderedCollection* stack)
  1343. {
  1344.     UndoOrderedCollectionIterator    iter(stack);
  1345.     UndoAction*            action;
  1346.  
  1347.     for (action = (UndoAction*)iter.First();
  1348.             iter.IsNotComplete();
  1349.             action = (UndoAction*)iter.Next())
  1350.     {
  1351.         delete action;
  1352.     }
  1353.     
  1354.     stack->RemoveAll();
  1355. }
  1356.  
  1357. //------------------------------------------------------------------------------
  1358. // SystemUndo::ClearActionsToMark
  1359. //
  1360. //    To make more efficient, should just start removing items from the front of
  1361. //    the list til I hit the mark.
  1362. //------------------------------------------------------------------------------
  1363.  
  1364. void SystemUndo::ClearActionsToMark(UndoOrderedCollection* stack)
  1365. {
  1366.     UndoOrderedCollectionIterator    collectionIter(stack);
  1367.     UndoAction*                    action;
  1368.     UndoOrderedCollection            elementsToDelete;
  1369.  
  1370.     // ADD ELEMENTS TO REMOVE TO A LIST
  1371.     for (action = (UndoAction*)collectionIter.First();
  1372.             collectionIter.IsNotComplete();
  1373.             action = (UndoAction*)collectionIter.Next())
  1374.     {
  1375.         if (action->fMark != kODFalse)
  1376.         {
  1377.             action->fMark = kODFalse;
  1378.             break;
  1379.         }
  1380.         else
  1381.             elementsToDelete.AddFirst(action);
  1382.     }
  1383.  
  1384.     // REMOVE ELEMENTS
  1385.     UndoOrderedCollectionIterator    deleteIter(&elementsToDelete);
  1386.     for (action = (UndoAction*)deleteIter.First();
  1387.             deleteIter.IsNotComplete();
  1388.             action = (UndoAction*)deleteIter.Next())
  1389.     {
  1390.         stack->Remove(action);
  1391.         delete action;
  1392.     }
  1393. }
  1394.  
  1395. //------------------------------------------------------------------------------
  1396. // SystemUndo::ClearActionHistory
  1397. //------------------------------------------------------------------------------
  1398.  
  1399. void SystemUndo::ClearActionHistory(ODRespectMarksChoices respectMarks)
  1400. {
  1401.     if (respectMarks == kODRespectMarks)
  1402.     {
  1403.         this->ClearActionsToMark(fUndoStack);
  1404.         this->ClearActionsToMark(fRedoStack);
  1405.     }
  1406.     else
  1407.     {
  1408.         this->ClearStack(fUndoStack);
  1409.         this->ClearStack(fRedoStack);
  1410.     }
  1411. }
  1412.  
  1413. //------------------------------------------------------------------------------
  1414. // SystemUndo::ClearRedoHistory
  1415. //------------------------------------------------------------------------------
  1416.  
  1417. void SystemUndo::ClearRedoHistory()
  1418. {
  1419.     this->ClearActionsToMark(fRedoStack);
  1420. }
  1421.  
  1422. //------------------------------------------------------------------------------
  1423. // SystemUndo::AbortCurrentTransaction
  1424. //------------------------------------------------------------------------------
  1425.  
  1426. void SystemUndo::AbortCurrentTransaction()
  1427. {
  1428.     ODULong            nestingLevel = 0;
  1429.     ODActionType    actionType;
  1430.  
  1431.     if (fCurrentlyUndoingOrRedoing)
  1432.         return;
  1433.     if (!fInTransaction)
  1434.         return;
  1435.     
  1436.     UndoAction* action = (UndoAction*)fUndoStack->First();
  1437.  
  1438.     do
  1439.     {
  1440.         if (action->fActionType == kODEndAction)
  1441.             ++nestingLevel;
  1442.         fUndoStack->RemoveFirst();
  1443.         actionType = action->fActionType;
  1444.         delete action;
  1445.         if (actionType == kODBeginAction && nestingLevel == 0)
  1446.             break;
  1447.         action = (UndoAction*)fUndoStack->First();//should never be NULL, right?
  1448.     }
  1449.     while (kODTrue);
  1450. }
  1451.  
  1452. //------------------------------------------------------------------------------
  1453. // SystemUndo::PeekUndoHistory
  1454. //------------------------------------------------------------------------------
  1455.  
  1456. ODBoolean SystemUndo::PeekUndoHistory(ODPart** part,
  1457.                                 ODActionData* actionData,
  1458.                                 ODActionType* actionType,
  1459.                                 ODName* actionLabel)
  1460. {
  1461.     return PeekHistory(part, actionData, actionType, actionLabel, kUndo);
  1462. }
  1463.  
  1464. //------------------------------------------------------------------------------
  1465. // SystemUndo::PeekRedoHistory
  1466. //------------------------------------------------------------------------------
  1467.  
  1468. ODBoolean SystemUndo::PeekRedoHistory(ODPart** part,
  1469.                                 ODActionData* actionData,
  1470.                                 ODActionType* actionType,
  1471.                                 ODName* actionLabel)
  1472. {
  1473.     return PeekHistory(part, actionData, actionType, actionLabel, kRedo);
  1474. }
  1475.  
  1476. //------------------------------------------------------------------------------
  1477. // SystemUndo::PeekHistory
  1478. //------------------------------------------------------------------------------
  1479.  
  1480. ODBoolean SystemUndo::PeekHistory(ODPart** part,
  1481.                                 ODActionData* actionData,
  1482.                                 ODActionType* actionType,
  1483.                                 ODName* actionLabel,
  1484.                                 ODUndoRedoType which)
  1485. {
  1486.     UndoOrderedCollection*    stack;
  1487.     ODIText*            iText;
  1488.  
  1489.     if (which == kUndo)
  1490.         stack = fUndoStack;
  1491.     else if (which == kRedo)
  1492.         stack = fRedoStack;
  1493.  
  1494.     UndoAction*    action = (UndoAction*)stack->First();
  1495.  
  1496.     if (!this->CheckActionOK(action))
  1497.         return kODFalse;
  1498.     else
  1499.     {
  1500.         if (action->fMark != kODFalse)
  1501.             return kODFalse;
  1502.         else
  1503.         {
  1504.             *part = action->fPart;
  1505.             *actionType = action->fActionType;
  1506.  
  1507.             *actionData = CopyByteArrayStruct(action->fActionData);
  1508.  
  1509.             if (which == kUndo)
  1510.                 iText = action->fUndoActionLabel;
  1511.             else if (which == kRedo)
  1512.                 iText = action->fRedoActionLabel;
  1513.  
  1514.             *actionLabel = CopyITextStruct(iText);
  1515.  
  1516.             return kODTrue;
  1517.         }
  1518.     }
  1519. }
  1520.  
  1521. //------------------------------------------------------------------------------
  1522. // NotifyUndoOrRedoOrDispose
  1523. //
  1524. //    Notify part to Undo or Redo or Dispose its data.
  1525. //    Could fine-tune to only pack parameters needed according to "which"
  1526. //    parameter
  1527. //------------------------------------------------------------------------------
  1528.  
  1529. static OSErr NotifyUndoOrRedoOrDispose(UndoAction* action,
  1530.                                                 ODUndoRedoType which)
  1531. {
  1532.     AEAddressDesc        address;
  1533.     AppleEvent            message;
  1534.     AppleEvent            reply;
  1535.     OSErr                error = noErr;
  1536.     ProcessSerialNumber    psn;
  1537.     Boolean                isSameProcess;
  1538.     DescType            eventID;
  1539. //    ProcessInfoRec        processRec;
  1540.  
  1541.     TRY
  1542. #if 0
  1543.         // MAKE SURE PROCESS IS STILL VALID. USE SIDE EFFECT OF ERROR RETURN
  1544.         //    FROM GetProcessInformation.
  1545.         processRec.processInfoLength = sizeof(ProcessInfoRec);
  1546.         processRec.processName = kODNULL;
  1547.         processRec.processAppSpec = kODNULL;
  1548.         THROW_IF_ERROR(GetProcessInformation(&action->fProcessNum, &processRec));
  1549. #endif /* 0 */
  1550.         // SOME CODE TO HANDLE THE SEND TO SELF CASE WELL. IF WE HAVE A STANDARD
  1551.         //    IDLE PROC TO USE, WE PROBABLY DON'T NEED THIS. (NP-WHAT DID I MEAN
  1552.         //    HERE?)
  1553.         THROW_IF_ERROR(GetCurrentProcess(&psn));
  1554.         THROW_IF_ERROR(SameProcess(&action->fProcessNum, &psn,
  1555.                                     &isSameProcess));
  1556.         if (isSameProcess)
  1557.         {
  1558.             psn.lowLongOfPSN = kCurrentProcess;
  1559.             psn.highLongOfPSN = 0;
  1560.         }
  1561.         else
  1562.             psn = action->fProcessNum;
  1563. #if 0
  1564.         {
  1565.             // MAKE SURE PROCESS IS STILL ALIVE.
  1566.             ODBoolean    processStillExists = kODFalse;
  1567.             
  1568.             while (kODTrue)
  1569.             {
  1570.                 if (GetNextProcess(&psn) != noErr)
  1571.                     break;
  1572.                 THROW_IF_ERROR(SameProcess(&action->fProcessNum, &psn,
  1573.                                             &isSameProcess));
  1574.                 if (isSameProcess)
  1575.                 {
  1576.                     processStillExists = kODTrue;
  1577.                     break;
  1578.                 }
  1579.             }
  1580.             
  1581.             if (!processStillExists)
  1582.                 THROW(procNotFound);
  1583.         }
  1584. #endif /* 0 */
  1585.         THROW_IF_ERROR(AECreateDesc(typeProcessSerialNumber,
  1586.                                     (Ptr)&psn, sizeof(psn), &address));
  1587.  
  1588.         if (which == kUndo)
  1589.             eventID = kUndoNotifyID;
  1590.         else if (which == kRedo)
  1591.             eventID = kRedoNotifyID;
  1592.         else if (which == kDispose)
  1593.             eventID = kDisposeActionNotifyID;
  1594.  
  1595.         THROW_IF_ERROR(AECreateAppleEvent(kODShellSignature, eventID,
  1596.                         &address, kAutoGenerateReturnID, kAnyTransactionID,
  1597.                         &message));
  1598.         TempAEDesc tempMessage(&message); // DMc make sure it is disposed
  1599.         
  1600.         THROW_IF_ERROR(AEPutParamPtr(&message, kDataPtrKeyword, typeChar,
  1601.                                     action->fActionData->_buffer,
  1602.                                     action->fActionData->_length));
  1603.         
  1604.         THROW_IF_ERROR(AEPutParamPtr(&message, kPartPtrKeyword, typeInteger,
  1605.                                     (Ptr)&action->fPart,
  1606.                                     sizeof(action->fPart)));
  1607.         
  1608.         THROW_IF_ERROR(AEPutParamPtr(&message, kDoneStateKeyword, typeInteger,
  1609.                                     (Ptr)&action->fDoneState,
  1610.                                     sizeof(action->fDoneState)));
  1611.         
  1612.         THROW_IF_ERROR(AESend(&message, &reply,
  1613.                             kAEWaitReply + kAECanInteract + kAECanSwitchLayer
  1614.                             + kAEDontRecord,
  1615.                             kAENormalPriority,
  1616.                             // NP: TEMP FIX: CHANGE TIMEOUT TO 5 SECONDS IF
  1617.                             //    SENDING A DISPOSE. *MAY* CAUSE MEMORY LEAKS,
  1618.                             //    OR, IN THE WORSE CASE, THAT SOME NOTIFICATIONS
  1619.                             //    WILL BE SENT AND OTHERS NOT. THIS MAY CONFUSE
  1620.                             //    A PART.
  1621.                             (which == kDispose ? 5 * 60 : kAEDefaultTimeout),
  1622.                             (AEIdleUPP)kODNULL,
  1623. //                            kAEDefaultTimeout, (AEIdleUPP)kODNULL,
  1624.                             (AEFilterUPP)kODNULL));
  1625.         AEDisposeDesc(&reply); // DMc
  1626.     CATCH_ALL
  1627.         error = ErrorCode();
  1628.     ENDTRY
  1629.     
  1630.     return error;
  1631. }
  1632.  
  1633. //------------------------------------------------------------------------------
  1634. // NotifyUndo
  1635. //
  1636. //    Call ODPart::Undo.
  1637. //------------------------------------------------------------------------------
  1638.  
  1639. static OSErr NotifyUndo(UndoAction* action)
  1640. {
  1641.     return NotifyUndoOrRedoOrDispose(action, kUndo);
  1642. }
  1643.  
  1644. //------------------------------------------------------------------------------
  1645. // NotifyRedo
  1646. //
  1647. //    Call ODPart::Redo.
  1648. //------------------------------------------------------------------------------
  1649.  
  1650. static OSErr NotifyRedo(UndoAction* action)
  1651. {
  1652.     return NotifyUndoOrRedoOrDispose(action, kRedo);
  1653. }
  1654.  
  1655. //------------------------------------------------------------------------------
  1656. // NotifyDispose
  1657. //
  1658. //    Call ODPart::DiposeActionState.
  1659. //------------------------------------------------------------------------------
  1660.  
  1661. static OSErr NotifyDispose(UndoAction* action)
  1662. {
  1663.     return NotifyUndoOrRedoOrDispose(action, kDispose);
  1664. }
  1665.  
  1666. //==============================================================================
  1667. // ODUndo
  1668. //==============================================================================
  1669.  
  1670. //------------------------------------------------------------------------------
  1671. // HandleUndoOrRedoOrDisposeNotify
  1672. //
  1673. //    Could fine-tune to only unpack parameters needed according to "which"
  1674. //    parameter
  1675. //------------------------------------------------------------------------------
  1676.  
  1677. static OSErr HandleUndoOrRedoOrDisposeNotify(AppleEvent* message,
  1678.                                                 AppleEvent* reply,
  1679.                                                 long refCon,
  1680.                                                 ODUndoRedoType which)
  1681. {
  1682.     ODUnused(reply);
  1683.     ODUnused(refCon);
  1684.  
  1685.     OSErr            error = noErr;
  1686.     DescType        gotType;
  1687.     ODActionData*    data;
  1688.     ODPart*            part;
  1689.     ODDoneState        doneState;
  1690.     Size            actualSize;
  1691.     Size            maximumDataSize;
  1692.     Size            maximumPartSize = sizeof(part);
  1693.     Size            maximumDoneStateSize = sizeof(doneState);
  1694.  
  1695.     TRY
  1696.         gotType = typeChar;
  1697.         THROW_IF_ERROR(AESizeOfParam(message, kDataPtrKeyword, &gotType,
  1698.                                         &actualSize));
  1699.         if (gotType != typeChar)
  1700.             THROW(errAECorruptData);
  1701.         maximumDataSize = actualSize;
  1702.         data = CreateEmptyByteArray(actualSize);
  1703.         THROW_IF_ERROR(AEGetParamPtr(message, kDataPtrKeyword, typeChar,
  1704.                                         &gotType, data->_buffer, maximumDataSize,
  1705.                                         &actualSize));
  1706.         if (actualSize != maximumDataSize)
  1707.             THROW(errAECorruptData);
  1708.  
  1709.         THROW_IF_ERROR(AEGetParamPtr(message, kPartPtrKeyword, typeInteger,
  1710.                                     &gotType, (Ptr)&part, maximumPartSize,
  1711.                                     &actualSize));
  1712.         if (gotType != typeInteger || actualSize != maximumPartSize)
  1713.             THROW(errAECorruptData);
  1714.         
  1715.         THROW_IF_ERROR(AEGetParamPtr(message, kDoneStateKeyword, typeInteger,
  1716.                                     &gotType, (Ptr)&doneState,
  1717.                                     maximumDoneStateSize,
  1718.                                     &actualSize));
  1719.         if (gotType != typeInteger || actualSize != maximumDoneStateSize)
  1720.             THROW(errAECorruptData);
  1721.         
  1722.         Environment*    ev = somGetGlobalEnvironment();
  1723.         if (which == kUndo)
  1724.         {
  1725.             part->UndoAction(ev, data);
  1726.             error = ODGetSOMException(ev);
  1727.         }
  1728.         else if (which == kRedo)
  1729.         {
  1730.             part->RedoAction(ev, data);
  1731.             error = ODGetSOMException(ev);
  1732.         }
  1733.         else if (which == kDispose)
  1734.         {
  1735.             part->DisposeActionState(ev, data, doneState);
  1736.             error = ODGetSOMException(ev);
  1737.         }
  1738.         
  1739.         DisposeByteArray(data);
  1740.         
  1741.     CATCH_ALL
  1742.         error = ErrorCode();
  1743.     ENDTRY
  1744.  
  1745.     return error;
  1746. }
  1747.  
  1748. //------------------------------------------------------------------------------
  1749. // HandleUndoNotify                
  1750. //------------------------------------------------------------------------------
  1751.  
  1752. static pascal OSErr HandleUndoNotify(AppleEvent* message, AppleEvent* reply,
  1753.                                         long refCon)
  1754. {
  1755.     return HandleUndoOrRedoOrDisposeNotify(message, reply, refCon, kUndo);
  1756. }
  1757.  
  1758. //------------------------------------------------------------------------------
  1759. // HandleRedoNotify                
  1760. //------------------------------------------------------------------------------
  1761.  
  1762. static pascal OSErr HandleRedoNotify(AppleEvent* message, AppleEvent* reply,
  1763.                                         long refCon)
  1764. {
  1765.     return HandleUndoOrRedoOrDisposeNotify(message, reply, refCon, kRedo);
  1766. }
  1767.  
  1768. //------------------------------------------------------------------------------
  1769. // HandleDisposeNotify                
  1770. //------------------------------------------------------------------------------
  1771.  
  1772. static pascal OSErr HandleDisposeNotify(AppleEvent* message, AppleEvent* reply,
  1773.                                         long refCon)
  1774. {
  1775.     return HandleUndoOrRedoOrDisposeNotify(message, reply, refCon, kDispose);
  1776. }
  1777.  
  1778. //------------------------------------------------------------------------------
  1779. // ODUndo::InitUndo
  1780. //------------------------------------------------------------------------------
  1781.  
  1782. SOM_Scope void  SOMLINK ODUndoInitUndo(ODUndo *somSelf, Environment *ev)
  1783. {
  1784.     ODUndoData *somThis = ODUndoGetData(somSelf);
  1785.     ODUndoMethodDebug("ODUndo","ODUndoInitUndo");
  1786.  
  1787.     /* Moved from somInit. SOM itself sets fields to zero
  1788.     _fSystemUndo = kODNULL;
  1789.     */
  1790.  
  1791.     TRY
  1792.         somSelf->InitObject(ev);
  1793.  
  1794.         _fSystemUndo = GetSystemUndo();
  1795.         if (!_fSystemUndo)
  1796.         {
  1797.             _fSystemUndo = new (kODSystemHeap) SystemUndo();
  1798.             if (_fSystemUndo)
  1799.             {
  1800.                 _fSystemUndo->Initialize();
  1801.                 SetSystemUndo(_fSystemUndo);
  1802.             }
  1803.         }
  1804.         THROW_IF_ERROR(AEInstallEventHandler(kODShellSignature,
  1805.                                     kUndoNotifyID,
  1806.                                     NewAEEventHandlerProc(HandleUndoNotify),
  1807.                                     (long)somSelf, !kIsSysHandler));
  1808.         THROW_IF_ERROR(AEInstallEventHandler(kODShellSignature,
  1809.                                     kRedoNotifyID,
  1810.                                     NewAEEventHandlerProc(HandleRedoNotify),
  1811.                                     (long)somSelf, !kIsSysHandler));
  1812.         THROW_IF_ERROR(AEInstallEventHandler(kODShellSignature,
  1813.                                     kDisposeActionNotifyID,
  1814.                                     NewAEEventHandlerProc(HandleDisposeNotify),
  1815.                                     (long)somSelf, !kIsSysHandler));
  1816.         _fSystemUndo->AddClient(somSelf);
  1817.     CATCH_ALL
  1818.         ODDeleteObject(_fSystemUndo);
  1819.         ODSetSOMException(ev, ErrorCode());
  1820.     ENDTRY
  1821. }
  1822.  
  1823. //------------------------------------------------------------------------------
  1824. // ODUndo::~ODUndo
  1825. //------------------------------------------------------------------------------
  1826.  
  1827. SOM_Scope void  SOMLINK ODUndosomUninit(ODUndo *somSelf)
  1828. {
  1829.     ODUndoData *somThis = ODUndoGetData(somSelf);
  1830.     ODUndoMethodDebug("ODUndo","ODUndosomUninit");
  1831.  
  1832.     if (_fSystemUndo)
  1833.     {
  1834.         _fSystemUndo->RemoveClient(somSelf);
  1835.         
  1836.         if (_fSystemUndo->GetNumClients() == 0) // reclaim space.
  1837.         {
  1838.     //        WARN("Deleting system undo object.");
  1839.             ODDeleteObject(_fSystemUndo);
  1840.             SetSystemUndo(kODNULL);
  1841.         }
  1842.     }
  1843.     ODUndo_parents_somUninit(somSelf);
  1844. }
  1845. #if 0
  1846. //------------------------------------------------------------------------------
  1847. // ODUndo::Purge
  1848. //------------------------------------------------------------------------------
  1849.  
  1850. SOM_Scope ODSize  SOMLINK ODUndoPurge(ODUndo *somSelf, Environment *ev,
  1851.         ODSize size)
  1852. {
  1853.     ODUndoData *somThis = ODUndoGetData(somSelf);
  1854.     ODUndoMethodDebug("ODUndo","ODUndoPurge");
  1855.  
  1856.     ODSize purged = 0;
  1857.     ODVolatile(purged);
  1858.     
  1859.     SOM_TRY
  1860.         if (_fSystemUndo) {
  1861.             purged =  _fSystemUndo->Purge(size);
  1862.         }
  1863.         else
  1864.             purged =  0;
  1865.  
  1866.         purged += parent_Purge(somSelf,ev,size);
  1867.     SOM_CATCH_ALL
  1868.         WARN("Error %ld trying to purge in ODUndoPurge",ErrorCode());
  1869.         SetErrorCode(kODNoError);        // dh - Eat the exception; Purge should not 
  1870.                                         // propagate it because clients function
  1871.                                         // fine whether memory was purged or not.
  1872.     SOM_ENDTRY
  1873.  
  1874.     return purged;
  1875. }
  1876. #endif /* 0 */
  1877. //------------------------------------------------------------------------------
  1878. // ODUndo::AddActionToHistory
  1879. //------------------------------------------------------------------------------
  1880.  
  1881. SOM_Scope void  SOMLINK ODUndoAddActionToHistory(ODUndo *somSelf, Environment *ev,
  1882.         ODPart* whichPart,
  1883.         ODActionData* actionData,
  1884.         ODActionType actionType,
  1885.         ODName* undoActionLabel,
  1886.         ODName* redoActionLabel)
  1887. {
  1888.     ODUndoData *somThis = ODUndoGetData(somSelf);
  1889.     ODUndoMethodDebug("ODUndo","ODUndoAddActionToHistory");
  1890.  
  1891.     SOM_CATCH
  1892.         return;
  1893.  
  1894.     if (_fSystemUndo)
  1895.         _fSystemUndo->AddActionToHistory(whichPart, actionData, actionType,
  1896.                                         undoActionLabel, redoActionLabel);
  1897.     else
  1898.         THROW(kODErrOutOfMemory);
  1899. }
  1900.  
  1901. //------------------------------------------------------------------------------
  1902. // ODUndo::Undo
  1903. //------------------------------------------------------------------------------
  1904.  
  1905. SOM_Scope void  SOMLINK ODUndoUndo(ODUndo *somSelf, Environment *ev)
  1906. {
  1907.     ODUndoData *somThis = ODUndoGetData(somSelf);
  1908.     ODUndoMethodDebug("ODUndo","ODUndoUndo");
  1909.  
  1910.     SOM_CATCH
  1911.         return;
  1912.  
  1913.     if (_fSystemUndo)
  1914.         _fSystemUndo->Undo();
  1915.     else
  1916.         THROW(kODErrEmptyStack);
  1917. }
  1918.  
  1919. //------------------------------------------------------------------------------
  1920. // ODUndo::Redo
  1921. //------------------------------------------------------------------------------
  1922.  
  1923. SOM_Scope void  SOMLINK ODUndoRedo(ODUndo *somSelf, Environment *ev)
  1924. {
  1925.     ODUndoData *somThis = ODUndoGetData(somSelf);
  1926.     ODUndoMethodDebug("ODUndo","ODUndoRedo");
  1927.  
  1928.     SOM_CATCH
  1929.         return;
  1930.  
  1931.     if (_fSystemUndo)
  1932.         _fSystemUndo->Redo();
  1933.     else
  1934.         THROW(kODErrEmptyStack);
  1935. }
  1936.  
  1937. //------------------------------------------------------------------------------
  1938. // ODUndo::MarkActionHistory
  1939. //------------------------------------------------------------------------------
  1940.  
  1941. SOM_Scope void  SOMLINK ODUndoMarkActionHistory(ODUndo *somSelf, Environment *ev)
  1942. {
  1943.     ODUndoData *somThis = ODUndoGetData(somSelf);
  1944.     ODUndoMethodDebug("ODUndo","ODUndoMarkActionHistory");
  1945.  
  1946.     SOM_CATCH
  1947.         return;
  1948.  
  1949.     if (_fSystemUndo)
  1950.         _fSystemUndo->MarkActionHistory();
  1951.     else
  1952.         THROW(kODErrCannotMarkAction);
  1953. }
  1954.  
  1955. //------------------------------------------------------------------------------
  1956. // ODUndo::ClearActionHistory
  1957. //------------------------------------------------------------------------------
  1958.  
  1959. SOM_Scope void  SOMLINK ODUndoClearActionHistory(ODUndo *somSelf, Environment *ev,
  1960.         ODRespectMarksChoices respectMarks)
  1961. {
  1962.     ODUndoMethodDebug("ODUndo","ODUndoClearActionHistory");
  1963.     ODUndoData *somThis = ODUndoGetData(somSelf);
  1964.  
  1965.     SOM_CATCH
  1966.         return;
  1967.  
  1968.     if (_fSystemUndo)
  1969.         _fSystemUndo->ClearActionHistory(respectMarks);
  1970. }
  1971.  
  1972. //------------------------------------------------------------------------------
  1973. // ODUndo::ClearRedoHistory
  1974. //------------------------------------------------------------------------------
  1975.  
  1976. SOM_Scope void  SOMLINK ODUndoClearRedoHistory(ODUndo *somSelf, Environment *ev)
  1977. {
  1978.     ODUndoMethodDebug("ODUndo","ODUndoClearRedoHistory");
  1979.     ODUndoData *somThis = ODUndoGetData(somSelf);
  1980.  
  1981.     SOM_CATCH
  1982.         return;
  1983.  
  1984.     if (_fSystemUndo)
  1985.         _fSystemUndo->ClearRedoHistory();
  1986. }
  1987.  
  1988. //------------------------------------------------------------------------------
  1989. // ODUndo::PeekUndoHistory
  1990. //------------------------------------------------------------------------------
  1991.  
  1992. SOM_Scope ODBoolean  SOMLINK ODUndoPeekUndoHistory(ODUndo *somSelf, Environment *ev,
  1993.         ODPart** part,
  1994.         ODActionData* actionData,
  1995.         ODActionType* actionType,
  1996.         ODName* actionLabel)
  1997. {
  1998.     ODUndoMethodDebug("ODUndo","ODUndoPeekUndoHistory");
  1999.     ODUndoData *somThis = ODUndoGetData(somSelf);
  2000.  
  2001.     SOM_CATCH
  2002.         return kODFalse;
  2003.  
  2004.     if (_fSystemUndo)
  2005.         return _fSystemUndo->PeekUndoHistory(part, actionData, actionType,
  2006.                                                 actionLabel);
  2007.     else
  2008.         return kODFalse;
  2009. }
  2010.  
  2011. //------------------------------------------------------------------------------
  2012. // ODUndo::PeekRedoHistory
  2013. //------------------------------------------------------------------------------
  2014.  
  2015. SOM_Scope ODBoolean  SOMLINK ODUndoPeekRedoHistory(ODUndo *somSelf, Environment *ev,
  2016.         ODPart** part,
  2017.         ODActionData* actionData,
  2018.         ODActionType* actionType,
  2019.         ODName* actionLabel)
  2020. {
  2021.     ODUndoMethodDebug("ODUndo","ODUndoPeekRedoHistory");
  2022.     ODUndoData *somThis = ODUndoGetData(somSelf);
  2023.  
  2024.     SOM_CATCH
  2025.         return kODFalse;
  2026.  
  2027.     if (_fSystemUndo)
  2028.         return _fSystemUndo->PeekRedoHistory(part, actionData, actionType,
  2029.                                                 actionLabel);
  2030.     else
  2031.         return kODFalse;
  2032. }
  2033.  
  2034. //------------------------------------------------------------------------------
  2035. // ODUndo::AbortCurrentTransaction
  2036. //------------------------------------------------------------------------------
  2037.  
  2038. SOM_Scope void  SOMLINK ODUndoAbortCurrentTransaction(ODUndo *somSelf, Environment *ev)
  2039. {
  2040.     ODUndoMethodDebug("ODUndo","ODUndoAbortCurrentTransaction");
  2041.     ODUndoData *somThis = ODUndoGetData(somSelf);
  2042.  
  2043.     SOM_CATCH
  2044.         return;
  2045.  
  2046.     if (_fSystemUndo)
  2047.         _fSystemUndo->AbortCurrentTransaction();
  2048. }
  2049.  
  2050.